import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';

export interface Material {
  id?: string;
  name: string;
  type: string;
  childType: string;
  code: string;
  specification: string;
  unit: string;
  price: number;
  quantity: number;
}

@Component({
  selector: 'app-material-in-item',
  templateUrl: './material-in-item.component.html',
  styleUrls: ['./material-in-item.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MaterialInItemComponent),
      multi: true,
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => MaterialInItemComponent),
      multi: true,
    }
  ],
})
export class MaterialInItemComponent implements OnInit, ControlValueAccessor {

  /**
   * 双向绑定物料详情
   */
  @Input() materials: Material[] = [];
  @Output() materialsChange: EventEmitter<Material[]> = new EventEmitter();

  /**
   * 双向绑定入库单总价
   */
  @Input() totalPrice = 0;
  @Output() totalPriceChange: EventEmitter<number> = new EventEmitter();

  // 固定每次添加的物料
  material: Material = {
    name: '电阻10K',
    type: '元器件',
    childType: '电阻',
    code: 'M-01-01-0001',
    specification: '0603-10K',
    unit: '个',
    price: 0,
    quantity: 0
  }

  // 这里是做一个空函数体，真正使用的方法在 registerOnChange 中
  // 由框架注册，然后我们使用它把变化发回表单
  // 注意，和 EventEmitter 尽管很像，但发送回的对象不同
  private propagateChange = (_: any) => {};

  constructor() {
  }

  writeValue(obj: any): void {
    if (obj) {
      this.materials = obj;
    }
  }

  // 当表单控件值改变时，函数 fn 会被调用
  // 这也是我们把变化 emit 回表单的机制
  registerOnChange(fn: any): void {
    this.propagateChange = fn;
  }

  public validate(c: FormControl) {
    let valid = true;
    if (this.materials.length === 0) {
      // 物料为空表单验证失败
      valid = false;
    }
    this.materials.forEach(item => {
      if (!item.price || !item.quantity || item.price === 0 || item.quantity === 0) {
        // 当有一项物料单价或数量为0或空都是失效
        valid = false;
      }
    })

    return valid ? null : {materials: true};
  }

  ngOnInit() {
  }

  addItem() {
    this.materials.push({...this.material});
    this.materialsChange.emit(this.materials);
    this.propagateChange(this.materials);
  }

  setTotalPrice() {
    this.totalPrice = 0;
    this.materials.forEach(item => this.totalPrice += item.quantity * item.price);
    this.propagateChange(this.materials);
    this.totalPriceChange.emit(this.totalPrice);
    this.materialsChange.emit(this.materials);
  }

  registerOnTouched(fn: any): void {
  }
}
